package org.six11.olive3.picturephone.server;

import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;

import com.mysql.jdbc.Driver;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import org.six11.olive3.server.DatabaseThing;
import org.six11.olive3.server.SqlStrings;
import org.six11.util2.Debug;

/**
 * A Batch process for rummaging through the database, finding things for players to do. This is a
 * somewhat time consuming process so it is best done in batches in separate threads.
 * 
 * @author Gabe Johnson <johnsogg@cmu.edu>
 */
public class TodoBatch {
//
//  /**
//   * @param args
//   *          optional sequence of user IDs. If not are provided, this tool runs the batch for all
//   *          users in the database.
//   */
//  public static void main(String[] args) throws ServletException {
//    Debug.useColor = false;
//    List<Integer> ids = new ArrayList<Integer>();
//    for (String s : args) {
//      ids.add(Integer.parseInt(s));
//    }
//    TodoBatch b = new TodoBatch();
//    if (ids.isEmpty()) {
//      b.processAll();
//    } else {
//      for (int i : ids) {
//        b.process(i);
//      }
//    }
//  }
//
//  public static int MIN_DEFICIT = 2; // if the user has fewer than this many sketches or
//                                     // descriptions to do, force the batch to run
//  public static String BATCH_SIZE = "4";
//  public static boolean EMIT_STATUS_TO_CONSOLE = false;
//
//  private DatabaseThing db;
//
//  public TodoBatch() throws ServletException {
//    MysqlDataSource dbSource = new MysqlDataSource();
//    dbSource.setServerName("localhost");
//    dbSource.setDatabaseName("sketching_games");
//    dbSource.setUser("olive");
//    dbSource.setPassword("secret");
//    db = new DatabaseThing(dbSource);
//  }
//
//  public TodoBatch(DataSource dataSource) {
//    this.db = new DatabaseThing(dataSource);
//  }
//
//  public TodoBatch(DatabaseThing db) {
//    this.db = db;
//  }
//
//  private void bug(String what) {
//    System.out.println("I am being called from: ");
//    (new RuntimeException("here")).printStackTrace();
//    Debug.out("TodoBatch", what);
//  }
//
//  private void bug(String what, List<Integer> ids) {
//
//    System.out.println("I am being called from: ");
//    (new RuntimeException("here")).printStackTrace();
//    bug(what + ": " + db.idListToCommaString(ids));
//  }
//
//  public void process(int i) throws ServletException {
//    int sketchCursor = 0;
//    int descCursor = 0;
//
//    Map<String, String> row = db.getRow("select max(id) from sketch", new String[] {});
//    String largestSketch = row.get("max(id)") == null ? "0" : row.get("max(id)");
//    int maxSketchCursor = Integer.parseInt(largestSketch);
//
//    row = db.getRow("select max(id) from description", new String[] {});
//    String largestDescription = row.get("max(id)") == null ? "0" : row.get("max(id)");
//    int maxDescCursor = Integer.parseInt(largestDescription);
//
//    if (EMIT_STATUS_TO_CONSOLE) {
//      System.out.print(i);
//    }
//
//    while (sketchCursor < maxSketchCursor || descCursor < maxDescCursor) {
//      if (EMIT_STATUS_TO_CONSOLE) {
//        System.out.print(".");
//      }
//      if (sketchCursor >= 0) {
//        sketchCursor = processSketch(i);
//      }
//      if (descCursor >= 0) {
//        descCursor = processDescriptions(i);
//      }
//      if (sketchCursor == -1 && descCursor == -1) {
//        break;
//      }
//    }
//
//  }
//
//  private int processSketch(int i) throws ServletException {
//    String uid = "" + i;
//
//    // First get the id of the first available sketch
//    Map<String, String> last_todo = db
//        .getRow("select last_todo_sketch from user where id = ?", uid);
//    // look for sketches the user can describe.
//    String lastSketchID = "0";
//    if (last_todo.containsKey("last_todo_sketch")) {
//      lastSketchID = last_todo.get("last_todo_sketch");
//    }
//
//    List<Integer> workingList = db.getIDs(
//        "select distinct id from sketch where user_id <> ? limit " + lastSketchID + ", "
//            + BATCH_SIZE, uid);
//    List<Integer> acceptedList = new ArrayList<Integer>();
//    List<Integer> rateList = new ArrayList<Integer>();
//
//    acceptedList.addAll(workingList);
//    rateList.addAll(workingList);
//    for (int sketchID : workingList) {
//
//      List<Integer> badParents = getBadParentsForSketch("" + sketchID, uid);
//      if (!badParents.isEmpty()) {
//        rateList.remove(new Integer(sketchID));
//      }
//      if (badParents.isEmpty()) {
//        List<Integer> goodParents = getGoodParentsForSketch("" + sketchID, uid);
//        for (int descID : goodParents) {
//          badParents = getBadParentsForDescription("" + descID, uid);
//          if (badParents.isEmpty()) {
//          } else {
//            rateList.remove(new Integer(sketchID));
//            acceptedList.remove(new Integer(sketchID));
//          }
//        }
//      } else {
//        acceptedList.remove(new Integer(sketchID));
//      }
//    }
//
//    // exclude sketches that have no grandparent
//    if (!rateList.isEmpty()) {
//      String sql = "select distinct s.id from sketch as s join "
//          + "description as d on s.description_id = d.id where s.id in ("
//          + db.idListToCommaString(rateList) + ") and d.sketch_id is null";
//      List<Integer> unrateable = db.getIDs(sql, new String[] {});
//      rateList.removeAll(unrateable);
//    }
//
//    // add all the sketches to rate
//    if (!rateList.isEmpty()) {
//      // ensure the user is not slated to do this
//      String checkSql = "select count(id) from todo_rate where user_id = ? and sketch_id = ?";
//      String insertSql = "insert into todo_rate (user_id, sketch_id) values (?, ?)";
//      for (int rateMe : rateList) {
//        String countString = db.getRow(checkSql, uid, "" + rateMe).get("count(id)");
//        if (new Integer(countString).intValue() == 0) {
//          db.insertRow(insertSql, uid, "" + rateMe);
//        }
//      }
//    }
//
//    int maxSketchID = -1;
//    if (!acceptedList.isEmpty()) {
//      String checkSql = "select count(id) from todo_sketch where user_id = ? and sketch_id = ?";
//      String insertSql = "insert into todo_sketch (user_id, sketch_id) values (?, ?)";
//      for (int acceptMe : acceptedList) {
//        if (acceptMe > maxSketchID) {
//          maxSketchID = acceptMe;
//        }
//        String countString = db.getRow(checkSql, uid, "" + acceptMe).get("count(id)");
//        if (new Integer(countString).intValue() == 0) {
//          db.insertRow(insertSql, uid, "" + acceptMe);
//        }
//      }
//
//      db.update("update user set last_todo_sketch = ? where id = ?", "" + maxSketchID, uid);
//    }
//    return maxSketchID;
//  }
//
//  private int processDescriptions(int i) throws ServletException {
//    String uid = "" + i;
//
//    Map<String, String> last_todo = db.getRow("select last_todo_describe from user where id = ?",
//        uid);
//    String lastDescID = "0";
//    if (last_todo.containsKey("last_todo_describe")) {
//      lastDescID = last_todo.get("last_todo_describe");
//    }
//    List<Integer> workingList = db.getIDs("select id from description where user_id <> ? limit "
//        + lastDescID + ", " + BATCH_SIZE, uid);
//    List<Integer> acceptedList = new ArrayList<Integer>();
//
//    acceptedList.addAll(workingList);
//
//    for (int descID : workingList) {
//
//      List<Integer> badParents = getBadParentsForDescription("" + descID, uid);
//      if (badParents.isEmpty()) {
//        List<Integer> goodParents = getGoodParentsForDescription("" + descID, uid);
//        for (int sketchID : goodParents) {
//          badParents = getBadParentsForSketch("" + sketchID, uid);
//          if (badParents.isEmpty()) {
//          } else {
//            acceptedList.remove(new Integer(descID));
//          }
//        }
//      } else {
//        acceptedList.remove(new Integer(descID));
//      }
//    }
//
//    int maxDescID = -1;
//    if (!acceptedList.isEmpty()) {
//      String checkSql = "select count(id) from todo_describe where user_id = ? and describe_id = ?";
//      String insertSql = "insert into todo_describe (user_id, describe_id) values (?, ?)";
//      for (int acceptMe : acceptedList) {
//        if (acceptMe > maxDescID) {
//          maxDescID = acceptMe;
//        }
//        String countString = db.getRow(checkSql, uid, "" + acceptMe).get("count(id)");
//        if (new Integer(countString).intValue() == 0) {
//          db.insertRow(insertSql, uid, "" + acceptMe);
//        }
//      }
//
//      db.update("update user set last_todo_describe = ? where id = ?", "" + maxDescID, uid);
//    }
//    return maxDescID;
//  }
//
//  private List<Integer> getBadParentsForSketch(String sid, String uid) throws ServletException {
//    return db.getIDs("select d.id from description as d join sketch as s on "
//        + "s.description_id = d.id where d.user_id = ? and s.id = ?", uid, sid);
//  }
//
//  private List<Integer> getGoodParentsForSketch(String sid, String uid) throws ServletException {
//    return db.getIDs("select d.id from description as d join sketch as s "
//        + "on s.description_id = d.id where d.user_id <> ? and s.id = ?", uid, sid);
//  }
//
//  private List<Integer> getBadParentsForDescription(String did, String uid) //
//      throws ServletException {
//    return db.getIDs("select s.id from sketch as s join description as d on "
//        + "s.id = d.sketch_id where s.user_id = ? and d.id = ?", uid, did);
//  }
//
//  private List<Integer> getGoodParentsForDescription(String did, String uid) //
//      throws ServletException {
//    return db.getIDs("select s.id from sketch as s join description as d on "
//        + "s.id = d.sketch_id where s.user_id <> ? and d.id = ?", uid, did);
//  }
//
//  public void processAll() throws ServletException {
//    EMIT_STATUS_TO_CONSOLE = true;
//    long start = System.currentTimeMillis();
//    List<Integer> allIds = db.getIDs("select id from user", null);
//    for (int id : allIds) {
//      process(id);
//    }
//    long end = System.currentTimeMillis();
//    long elapsed = end - start;
//    long sec = elapsed / 1000;
//    long ms = elapsed % 1000;
//    System.out.println("\nDone (" + sec + "." + ms + " seconds elapsed)");
//  }
//
//  /**
//   * @param intValue
//   */
//  public void processUserInBackgroundThread(final int userID) {
//    Runnable r = new Runnable() {
//      public void run() {
//        try {
//          Debug.out("TodoBatch", "Starting to process user " + userID + " in the background.");
//          new TodoBatch().process(userID);
//          Debug.out("TodoBatch", "Done procssing user " + userID + " in the background.");
//
//        } catch (ServletException ex) {
//          Debug.out("TodoBatch", "Failed to process user " + userID + " in the background.");
//          ex.printStackTrace();
//        }
//      }
//    };
//    new Thread(r).start();
//  }
//
//  public void processUserInBackgroundWhenNecessary(final int userID) {
//    String uidString = "" + userID;
//    try {
//      int userSketchCount = db.getInt(SqlStrings.COUNT_TODO_SKETCH, uidString);
//      int userDescCount = db.getInt(SqlStrings.COUNT_TODO_DESCRIBE, uidString);
//
//      if (userSketchCount < MIN_DEFICIT || userDescCount < MIN_DEFICIT) {
//        processUserInBackgroundThread(userID);
//      }
//    } catch (ServletException ex) {
//      ex.printStackTrace();
//    }
//  }

}
